package cn.sstech.member.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ExchangeUtil {
	
	static Logger logger = LoggerFactory.getLogger(ExchangeUtil.class);
	
	public static <T> List<T> iteratorToList(Iterator<T> i){
		List<T> list = new ArrayList<T>();
		if(null == i){
			return list;
		}
		else{
			while(i.hasNext()){
				list.add(i.next());
			}
		}
		
		return list;
	}
	
//	public static <T> Page<T> listToPage(List<T> list){
//		Page<T> result = new Page<T>() {
//			
//		};
//	}
	
	/**
	 * 将list转换成树形结构
	 * 
	 * map里放入
	 * parentIdFieldName : 父节点id字段名
	 * idFieldName : id字段名
	 * childNodeFieldName : 子节点list字段名
	 * 
	 * nodeClass : 节点类路径
	 * idAndParentIdClass : id字段的类路径 （默认Integer）
	 * 
	 * @param nodes
	 * @return
	 */
	public static <T> List<T> buildTree(List<T> nodes,Map<String,Object> classParam) throws Exception 
			{
		if(!classParam.containsKey("parentIdFieldName")){
			classParam.put("parentIdFieldName", "parentId");
		}
		if(!classParam.containsKey("idFieldName")){
			classParam.put("idFieldName", "id");
		}
		if(!classParam.containsKey("childNodeFieldName")){
			throw new Exception("leak of childNodeFieldName");
		}
		if(!classParam.containsKey("nodeClass")){
			throw new Exception("leak of nodeClass");
		}
		if(!classParam.containsKey("idAndParentIdClass")){
			throw new Exception("leak of idAndParentIdClass");
		}

		List<T> rootNodes = new ArrayList<T>();
		
		List<T> nodesBesidesLeafs = new ArrayList<T>();;
		try {
			nodesBesidesLeafs = buildTreeByList(nodes,classParam);
		} catch (NoSuchMethodException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		} catch (SecurityException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		} catch (NoSuchFieldException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		} catch (IllegalArgumentException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		} catch (IllegalAccessException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		} catch (InvocationTargetException e) {
			logger.error(e.getMessage(),e);
			return new ArrayList<T>();
		}
		if(!nodes.equals(nodesBesidesLeafs)){
			rootNodes = buildTree(nodesBesidesLeafs,classParam);
		}
		else{
			rootNodes = nodesBesidesLeafs;
		}
		
		return rootNodes;
	}
	/**
	 * 获取除了叶子节点以外的所有节点
	 * 
	 * map里放入
	 * parentIdFieldName : 父节点id字段名
	 * idFieldName : id字段名
	 * childNodeFieldName : 子节点list字段名
	 * 
	 * nodeClass : 节点类路径
	 * idAndParentIdClass : id字段的类路径 （默认Integer）
	 * 
	 * @param nodes
	 * @return
	 */
	static <T> List<T> buildTreeByList(List<T> nodes,Map<String,Object> classParam) 
			throws NoSuchMethodException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException{
		
		List<T> nodesLeafs = new ArrayList<T>();
		List<T> nodesBesidesLeafs = new ArrayList<T>();

		String parentIdFieldName = String.valueOf(classParam.get("parentIdFieldName"));
		String idFieldName = String.valueOf(classParam.get("idFieldName"));
		String childNodeFieldName = String.valueOf(classParam.get("childNodeFieldName"));
		
		Class<?> nodeClass = Class.forName(String.valueOf(classParam.get("nodeClass")));
		Class<?> idAndParentIdClass = Class.forName(String.valueOf(classParam.get("idAndParentIdClass")));
		if(null == idAndParentIdClass){
			idAndParentIdClass = Integer.class;
		}
		
		Method equalsMethod = idAndParentIdClass.getMethod("equals",Object.class);
		
		Field parentIdField = null;
		Field idField = null;
		Field childNodeField = null;
		
		do{
			Field[] fildList = nodeClass.getDeclaredFields();
			for(int i=0;i<fildList.length;i++){
				if(fildList[i].getName().equals(parentIdFieldName)){
					parentIdField = fildList[i];
				}
				else if(fildList[i].getName().equals(idFieldName)){
					idField = fildList[i];
				}
				else if(fildList[i].getName().equals(childNodeFieldName)){
					childNodeField = fildList[i];
				}
			}
			nodeClass = nodeClass.getSuperclass();
		}while(!((null != parentIdField && null != idField && null != childNodeField) ||
				nodeClass.getDeclaredFields().length <= 0));
		
		parentIdField.setAccessible(true);
		idField.setAccessible(true);
		childNodeField.setAccessible(true);

		if(null == nodes || nodes.isEmpty()){
			return new ArrayList<T>();
		}
		int nodesSize = nodes.size();
		for(int i=0;i<nodesSize;i++){
			boolean hasLeafNodes = false;
			boolean hasFatherNodes = false;
			for(int j=0;j<nodesSize;j++){

				if( false == hasLeafNodes && null != parentIdField.get(nodes.get(i)) && null != parentIdField.get(nodes.get(j)) &&
						(Boolean) equalsMethod.invoke(idField.get(nodes.get(i)), parentIdField.get(nodes.get(j))) 
						){
					hasLeafNodes = true;
				}
				
				if( false == hasFatherNodes && null != parentIdField.get(nodes.get(i)) && null != parentIdField.get(nodes.get(j)) &&
						(Boolean) equalsMethod.invoke(parentIdField.get(nodes.get(i)), idField.get(nodes.get(j)))
						){
					hasFatherNodes = true;
					
					Object childNode = childNodeField.get(nodes.get(j));
					if(null == childNode){
						childNode = new ArrayList<T>();
						childNodeField.set(nodes.get(j), childNode);
					}
					
					@SuppressWarnings("unchecked")
					List<T> childNodeList = (List<T>) childNode;
					if(!childNodeList.contains(nodes.get(i))){
						childNodeList.add(nodes.get(i));
					}
				}

			}
			
			if(hasFatherNodes && !hasLeafNodes
					&& !nodesLeafs.contains(nodes.get(i))){
				nodesLeafs.add(nodes.get(i));
			}
		}
		
		nodesBesidesLeafs.addAll(nodes);
		nodesBesidesLeafs.removeAll(nodesLeafs);
		return nodesBesidesLeafs;
	}
}
